package ms.jacrim.tropos;

import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Element;

public abstract class TroposObject {
	
	public static final String ACTOR = "tr:Actor";
	public static final String DEPENDENCY = "tr:Dependency";
	public static final String MEANS_END = "tr:MeansEnd";
	public static final String CONTRIBUTION = "tr:Contribution";
	public static final String COMPOSITION = "tr:Composition";
	public static final String OWNERSHIP = "tr:Ownership";
	public static final String ASSOCIATION = "tr:Association";
	public static final String SERVICE = "tr:Service";
	
	private static Map<String, Class<? extends TroposObject>> OCM; // ObjectClassMapping
	
	private String type;
	private String id;
	private String name;
	private UID notationID;
	
	protected Diagram diagram;
	
	TroposObject(Diagram diagram)
	{
		this.diagram = diagram;
		id = Integer.toHexString(System.identityHashCode(this));
	}
	TroposObject(Diagram diagram, TroposObject sourceObj) {
		this.diagram = diagram;
		type = sourceObj.type;
		id = sourceObj.id;
		name = sourceObj.name;
	}
	
	TroposObject(Diagram diagram, Element element){
		this.diagram = diagram;
		this.populate(element);
	}
	
	static void initializeObjectMappings() {
		if (OCM == null) {
			OCM = new HashMap<String, Class<? extends TroposObject>>();
			OCM.put(ACTOR, Actor.class); //metadata
			OCM.put(COMPOSITION, Composition.class);
			OCM.put(CONTRIBUTION, Contribution.class);
			OCM.put(DEPENDENCY, Dependency.class);
			OCM.put(MEANS_END, MeansEnd.class);
			OCM.put(OWNERSHIP, Ownership.class);
			OCM.put(ASSOCIATION, Association.class);
			OCM.put(SERVICE, Service.class);
		}
	}
	
	static TroposObject createObjectFromElement(Diagram diagram, Element element) throws Exception {
		initializeObjectMappings();
		
		TroposObject result = null;
		String objType = element.getAttribute("xmi:type");
		
		Class<? extends TroposObject> objClass = OCM.get(objType);
		if (objClass != null)
			result = objClass.getConstructor(Diagram.class, Element.class).newInstance(diagram, element);
		else
			System.out.println("Unknown object type: " + objType);
		return result;
	}
	
	void populate(Element element){
		type = element.getAttribute("xmi:type");
		id = element.getAttribute("xmi:id");
		name = element.getAttribute("name");
	}
	
	public void setType(String type){
		this.type = type;
	}
	
	public String getType(){
		return type;
	}
	
	public String getId(){
		return id;
	}
	
	public UID getNotationID() {
		if (notationID == null) notationID = UID.generate();
		return notationID;
	}
	
	public void setName(String name){
		this.name = name;
	}
	
	public String getName(){
		return name;
	}
	
	public String getNormalizeName() {
		String result = name.trim().replace(' ', '_');
		return result;
	}
	
	public Diagram getDiagram() {
		return diagram;
	}

	void setDiagram(Diagram diagram) {
		this.diagram = diagram;
	}

	void toString(StringBuilder result, int part, int indent) {
		
	}
	
	protected void writeIndent(StringBuilder result, int indent) {
		for(int i = 0; i < indent; i++)
			result.append("\t");
	}
}
